﻿using System.Collections.Generic;
using System.Linq;
using System.Web;
using CID.Domain.Operations;
using System.ComponentModel.DataAnnotations;
using System.Web.Mvc;
using Newtonsoft.Json;
using CID.Web.Models.Users;
using CID.Domain.Users;

namespace CID.Web.Models.Operations
{
    public class EnvironmentViewModel : BaseDescribedViewModel<IEnvironment>, IAjaxEnabledViewModel
    {
        #region Properties
        [Display(Name="Is Production")]
        public bool IsProduction { get; set; }

        public bool Enabled { get; set; }

        [HiddenInput(DisplayValue = false)]
        [Required(ErrorMessage = "You must provide a Responsible")]
        public int? ResponsibleId { get; set; }
        public string Responsible { get; set; }

        public List<ServerAssignmentViewModel> Assignments { get; set; }

        public string PostUrl { get; set; }
        #endregion

        public EnvironmentViewModel() : base() 
        {
            Assignments = new List<ServerAssignmentViewModel>();
        }

        public EnvironmentViewModel(IEnvironment model) : base(model)
        {
            Assignments = new List<ServerAssignmentViewModel>();
            Enabled = model.Enabled;
            IsProduction = model.IsProduction;

            if (model.Responsible != null)
            {
                ResponsibleId = model.Responsible.Id;
                Responsible = model.Responsible.Name;
            }

            foreach (var assignment in model.Assignments)
                Assignments.Add(new ServerAssignmentViewModel(assignment));
        }

        public override void UpdateModel(IEnvironment model)
        {
            base.UpdateModel(model);
            model.Enabled = Enabled;
            model.IsProduction = IsProduction;
            model.Responsible = availableUsers.SingleOrDefault(x => x.Id == ResponsibleId.Value);

            foreach (var removedAssignment in RemovedAssignments)
            {
                var assignment = model.Assignments.SingleOrDefault(x => x.Id == removedAssignment.Id);
                model.RemoveAssignment(assignment);
            }

            foreach (var insertedAssignment in InsertedAssignments)
                model.Assign(GetServer(insertedAssignment), GetServerRole(insertedAssignment));
        }

        private IEnumerable<ServerAssignmentViewModel> InsertedAssignments
        {
            get { return Assignments.Where(x => ((x.Id == 0) && !x._destroy)); }
        }

        private IEnumerable<ServerAssignmentViewModel> RemovedAssignments
        {
            get { return Assignments.Where(x => ((x.Id != 0) && x._destroy)); }
        }

        #region Helper Members
 
        #region User helper members
        private IEnumerable<User> availableUsers;

        [JsonIgnore]
        public IEnumerable<UserViewModel> AvailableUsers
        {
            get { return availableUsers.ToList().Select(x => new UserViewModel(x)); }
        }

        public void SetAvailableUsers(IEnumerable<User> availableUsers)
        {
            this.availableUsers = availableUsers.ToArray();
        }

        #endregion

        #region ServerRole helper members
        private IEnumerable<ServerRole> availableServerRoles;

        public void SetAvailableServerRoles(IEnumerable<ServerRole> availableServerRoles)
        {
            this.availableServerRoles = availableServerRoles.ToArray();
        }
        #endregion

        #region Server helper members
        private IEnumerable<Server> availableServers;

        public void SetAvailableServers(IEnumerable<Server> availableServers)
        {
            this.availableServers = availableServers.ToArray();
        }
        #endregion

        public ServerAssignmentViewModel NewServerAssignment()
        {
            var result = new ServerAssignmentViewModel();
            result.SetAvailableServers(availableServers);
            result.SetAvailableServerRoles(availableServerRoles);

            return result;
        }

        private IServer GetServer(ServerAssignmentViewModel assignment)
        {
            return availableServers.SingleOrDefault(x => x.Id == assignment.ServerId);
        }

        private IServerRole GetServerRole(ServerAssignmentViewModel assignment)
        {
            return availableServerRoles.SingleOrDefault(x => x.Id == assignment.ServerRoleId);
        }
        #endregion

    }
}